define(["collisionlistener",
        "imagerepository",
        "spritebuffer",
        "levelbuilder",
        "levelarray",
        "background",
        "bouncer", 
        "ball",
        "stats"], function(
        CollisionListener,
        ImageRepository,
        SpriteBuffer,
        LevelBuilder,
        levelArray,
        Background, 
        Bouncer,
        Ball,
        Stats){
    
    var GameController = function()
    {
        var gamePaused = true;
        var contextBackground = null;
        var contextBouncer = null;
        var contextBall = null;
        var contextLevel = null;
        var contextStats = null;
        var collisionListener = null;
        var imageRepository = null;
        var spriteBuffer = null;
        var levelBuilder = null;
        
        var background = null;
        var bouncer = null;
        var ball = null;
        var stats = null;
        var currentLevel = null;

        var getCanvasContext = function(canvasName){
            var context = document.getElementById(canvasName).getContext('2d');
            return context;
        };    
        
        var nextLevel = function(levelNumber){
            
            pause();
            
            currentLevel = levelBuilder.buildLevel( levelNumber );            
            stats.setLevelName( "Level " + currentLevel.levelNumber );
            imageRepository.loadBackground(currentLevel.background, function(image){
                background  = new Background(image);
                resume();
            });
            
            collisionListener.reset();
            collisionListener.registerCollidable(bouncer); 
            collisionListener.registerCollidableArray(currentLevel.blocks); 
        };
        
        var resume = function(){
            gamePaused = false;
            
        };
        
        var pause = function(){
            gamePaused = true;
        };
        
        var exec = function() {                    
            
            requestAnimationFrame(exec);
            if(gamePaused){
                return;
            }
            
            background.draw(contextBackground);    
            bouncer.draw(contextBouncer);
            ball.draw(contextBall);                        
            currentLevel.draw(contextLevel);
            stats.draw(contextStats);
            
            if(currentLevel.hasFinished()){            
                nextLevel( currentLevel.levelNumber + 1 );                
            }
            
            collisionListener.listen();              
        };
        
        var imageRepositoryReady = function(){            
            spriteBuffer = new SpriteBuffer(imageRepository.imgSprites);
            levelBuilder = new LevelBuilder(levelArray, spriteBuffer);            
            bouncer = new Bouncer(spriteBuffer.getSprite(0,200,96,24));            
            ball = new Ball(spriteBuffer.getSprite(160,200,16,16));  
            stats = new Stats();
            collisionListener = new CollisionListener(ball, stats);
            nextLevel(1);
            requestAnimationFrame(exec);
        };
        
        // ------------ Public API ------------------
        
        this.start = function(){
            contextBackground = getCanvasContext('bg');
            contextBouncer = getCanvasContext('bouncer');
            contextBall = getCanvasContext('ball');            
            contextLevel = getCanvasContext('level');
            contextStats = getCanvasContext('stats');
            imageRepository = new ImageRepository(imageRepositoryReady);             
        };
                
    };    
        
    return new GameController();
});

